package com.gitee.huanminabc.jcommon.str;

import com.gitee.huanminabc.jcommon.exception.CommonException;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.*;
import java.util.function.Consumer;

/**
 * 简要描述
 *
 * @Author: mac
 * @Date: 2025/4/3 12:08
 * @Version: 1.0
 * @Description: 文件作用详细描述....
 */
public class StringUtil {

    //splitComma
    public static String[] splitComma(String str) {
        if (str == null || str.isEmpty()) {
            return new String[0];
        }
        return str.split(",");
    }



    /**
     * 判断字符串为空  为空返回 true
     * @param str
     * @return
     */
    public static boolean isEmpty(CharSequence str) {
        final int strLen = str == null ? 0 : str.length();
        if (strLen == 0) {
            return true;
        }
        for (int i = 0; i < strLen; i++) {
            if (!Character.isWhitespace(str.charAt(i))) {
                return false;
            }
        }
        return true;
    }

    //任意一个参数是空返回true
    public static boolean isAnyEmpty(String... str) {
        for (String s : str) {
            if (isEmpty(s)) {
                return true;
            }
        }
        return false;
    }


    public static boolean isNotEmpty(String str) {
        return !isEmpty(str);
    }

    //全部参数都不为空返回true
    public static boolean isAllNotEmpty(String... str) {
        for (String s : str) {
            if (isEmpty(s)) {
                return false;
            }
        }
        return true;
    }


    public static boolean equals(String str1, String str2) {
        if (str1 == null && str2 == null) {
            return true;
        }
        if (str1 == null || str2 == null) {
            return false;
        }
        return str1.equals(str2);
    }

    //判断多个字符串是否相等,只要有一个相等就返回true,否则返回false
    public static boolean equalsAny(String str1, String... str2) {
        for (String s : str2) {
            if (str1.equals(s)) {
                return true;
            }
        }
        return false;
    }

    //字符串比较,同时比较多个字符串,只要一个等就返回false,如果都不等就返回true
    public static boolean equalsNotAny(String str, String... strs) {
        for (String s : strs) {
            if (str.equals(s)) {
                return false;
            }
        }
        return true;
    }

    //判断多个字符串是否相等,全部相等才返回true,否则返回false
    public static boolean equalsAll(String str1, String... str2) {
        for (String s : str2) {
            if (!str1.equals(s)) {
                return false;
            }
        }
        return true;
    }





    //首字母转小写
    public static String toLowerCaseFirstChar(String s) {
        if (Character.isLowerCase(s.charAt(0))) {
            return s;
        } else {
            return Character.toLowerCase(s.charAt(0)) + s.substring(1);
        }
    }


    //首字母转大写
    public static String toUpperCaseFirstChar(String s) {
        if (Character.isUpperCase(s.charAt(0))) {
            return s;
        } else {
            return Character.toUpperCase(s.charAt(0)) + s.substring(1);
        }
    }







    //字符串查找指定长度 从指定位置开始到什么位置结束 ,start从0开始 ,end从1开始
    public static int findRange(String str, String search, int start, int end) {
        int i = start;
        int j = 0;
        int k = 0;
        int len = str.length();
        int search_len = search.length();
        while (i < len && i < end) {
            if (str.charAt(i) == search.charAt(j)) {
                k = i;
                while (j < search_len && str.charAt(k) == search.charAt(j)) {
                    k++;
                    j++;
                }
                if (j == search_len) {
                    return i;
                }
                j = 0;
            }
            i++;
        }
        return -1;
    }

    //替换指定范围内所有的字符串, str1:源字符串  str2:要替换的字符串, str3:替换为什么  start:开始位置  end:结束位置  start从0开始 ,end从1开始
    public static String replaceRangeAll(String str1, String str2, String str3, int start, int end) {
        int i = findRange(str1, str2, start, end);
        if (i == -1) {
            return str1;
        }
        int len1 = str1.length();
        int len2 = str2.length();
        int len3 = str3.length();
        char[] str = new char[len1 - len2 + len3];
        int j = 0;
        int k = 0;
        while (j < i) {
            str[j] = str1.charAt(j);
            j++;
        }
        while (k < len3) {
            str[j] = str3.charAt(k);
            j++;
            k++;
        }
        k = i + len2;
        while (k < len1) {
            str[j] = str1.charAt(k);
            j++;
            k++;
        }
//        str[j] = '\0';  在java中不需要
        return replaceRangeAll(new String(str), str2, str3, i, end);
    }




    //计算两个字符串的相似度,返回百分比 0-100
    public static int getSimilarityRatio(String str, String target) {
        int[][] d; // 矩阵
        int n = str.length();
        int m = target.length();
        int i; // 遍历str的
        int j; // 遍历target的
        char ch1; // str的
        char ch2; // target的
        int temp; // 记录相同字符,在某个矩阵位置值的增量,不是0就是1
        if (n == 0) {
            return m;
        }
        if (m == 0) {
            return n;
        }
        d = new int[n + 1][m + 1];
        for (i = 0; i <= n; i++) { // 初始化第一列
            d[i][0] = i;
        }

        for (j = 0; j <= m; j++) { // 初始化第一行
            d[0][j] = j;
        }

        for (i = 1; i <= n; i++) { // 遍历str
            ch1 = str.charAt(i - 1);
            // 去匹配target
            for (j = 1; j <= m; j++) {
                ch2 = target.charAt(j - 1);
                if (ch1 == ch2) {
                    temp = 0;
                } else {
                    temp = 1;
                }
                // 左边+1,上边+1, 左上角+temp取最小
                d[i][j] = min(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1]
                        + temp);
            }
        }
        return 100 - d[n][m] * 100 / Math.max(str.length(), target.length());
    }
    private static int min(int one, int two, int three) {
        return (one = Math.min(one, two)) < three ? one : three;
    }


    //获取n~n之间的所有连续数字的字符串
    public static List<String> getRange(String start, String end) {
        if (start == null || end == null) {
            return null;
        }
        if (!StringIdentifyUtil.isNumeric(start) || !StringIdentifyUtil.isNumeric(end)) {
            return null;
        }
        int start_int = Integer.parseInt(start);
        int end_int = Integer.parseInt(end);
        List<String> pList = new ArrayList<>(end_int - start_int + 1);
        for (int i = start_int; i <= end_int; i++) {
            String str = String.valueOf(i);
            pList.add(str);
        }
        return pList;
    }



    //最好的hash算法,冲突较少,效率较高
    public static int getHashCode(String str) {
        int hash = 0;
        int seed = 131;
        for (int i = 0; i < str.length(); ++i) {
            hash = hash * seed + str.charAt(i);
        }
        return (hash & 0x7FFFFFFF);
    }


    //提取字符串中的中文
    public static String extractChinese(String str) {
        char[] charArray = str.toCharArray();
        StringBuilder result = new StringBuilder();

        for (char c : charArray) {
            if (c >= '\u4e00' && c <= '\u9fa5') {
                result.append(c);
            }
        }

        return result.toString();
    }

    /**
     * 取出一个字符串所有可能的连续子串,正反顺序都取
     * 比如: abc 取出 a,ab,abc,b,bc,c,ba,bac,cba,cba
     * 限制最小长度
     * @param str
     * @param length
     * @return
     */
    public static List<String> getSubString(String str, int length) {
        List<String> list = new ArrayList<>();
        if (str == null || str.length() < length) {
            return list;
        }
        for (int i = 0; i < str.length(); i++) {
            for (int j = str.length(); j > i; j--) {
                //去除空格
                String substring = str.substring(i, j).trim();
                if (substring.length() < length) {
                    continue;
                }
                list.add(substring);
            }
        }
        //反向
        for (int i = str.length(); i > 0; i--) {
            for (int j = 0; j < i; j++) {
                String substring = str.substring(j, i).trim();
                if (substring.length() < length) {
                    continue;
                }
                list.add(substring);
            }
        }
        //去重
        HashSet<String> hashSet = new HashSet<>(list);
        list.clear();
        list.addAll(hashSet);
        return list;
    }

    //字符串按行读取
    public static void readStrLine(String str, Consumer<String> consumer) {

        try (BufferedReader br = new BufferedReader(new StringReader(str))) {
            String line;
            while ((line = br.readLine()) != null) {
                consumer.accept(line);
            }
        } catch (IOException e) {
            throw new CommonException(e);
        }
    }


    //字符串*n次拼接
    public static String concat(String str, int n) {
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < n; i++) {
            stringBuilder.append(str);
        }
        return stringBuilder.toString();
    }

    //统计字符串中某个字符出现的次数
    public static int countChar(String str, char target) {
        int count = 0;
        for (int i = 0, len = str.length(); i < len; i++) {
            if (str.charAt(i) == target) {
                count++;
            }
        }
        return count;
    }
    //统计字符串中某个字符串出现的次数
    public static int countStr(String str, String target) {
        int count = 0;
        int index = 0;
        while ((index = str.indexOf(target, index)) != -1) {
            count++;
            index += target.length();
        }
        return count;

    }



    //将_转为驼峰  user_name -> userName  小写驼峰
    public static String toCamelCase(String s) {
        if (s == null) {
            return null;
        }
        s = s.toLowerCase();
        StringBuilder sb = new StringBuilder();

        boolean upperCase = false;
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);

            if (c == '_') {
                upperCase = true;
            } else if (upperCase) {
                sb.append(Character.toUpperCase(c));
                upperCase = false;
            } else {
                sb.append(c);
            }
        }

        return sb.toString();
    }


    //将_转为驼峰  user_name -> UserName  大写驼峰
    public static String toUpperCamelCase(String s) {
        String camelCase = toCamelCase(s);
        if (camelCase == null || camelCase.isEmpty()) {
            return camelCase;
        }
        return Character.toUpperCase(camelCase.charAt(0)) + camelCase.substring(1);
    }

    //将驼峰转为下划线  userName -> user_name
    public static String toUnderline(String s) {
        if (s == null) {
            return null;
        }

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);

            if (Character.isUpperCase(c)) {
                sb.append('_').append(Character.toLowerCase(c));
            } else {
                sb.append(c);
            }
        }
        //如果存在大于1个下划线,那么就只保留一个下划线
        return sb.toString().replaceAll("_+", "_");
    }
}
